package com.suning.sawp.service.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.URLEncoder;
import java.util.List;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVPrinter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Charsets;

/**
 * CSV工具类
 *
 * @author 15050519
 * @see [相关类/方法]（可选）
 * @since [产品/模块版本] （可选）
 */
public class CsvUtils {

    /**
     * 日志
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(CsvUtils.class);

    // CSV文件分隔符
    private static final String NEW_LINE_SEPARATOR = "\n";

    // 写流字节大小
    private static final int WRITE_SIZE = 1024;

    // If you do not want a UTF-8 ,just replace the byte array.
    private static final byte commonCsvHead[] = { (byte) 0xEF, (byte) 0xBB, (byte) 0xBF };

    /**
     * 创建临时文件
     *
     * @param fileName
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static File createCsvFile(String fileName) {
        LOGGER.info("createCsvFile enter, fileName={}", fileName);
        File file = null;
        OutputStream os = null;
        try {
            file = File.createTempFile(fileName, ".csv");
            // utf-8 bom写到文件信息中,防止UTF-8编码在excel显示中文乱码
            os = new FileOutputStream(file);
            os.write(commonCsvHead);
            os.flush();
            LOGGER.debug("createTempFile file={}", file);
        } catch (FileNotFoundException e) {
            LOGGER.error("createCsvFile FileNotFoundException ERROR", e);
        } catch (IOException e) {
            LOGGER.error("createCsvFile error", e);
        } finally {
            if (null != os) {
                try {
                    os.close();
                } catch (IOException e) {
                    LOGGER.error("createCsvFile close FileOutputStream ERROR", e);
                }
            }

        }
        LOGGER.info("createCsvFile end, fileName={}", fileName);
        return file;
    }

    /**
     * 将数据写进csv文件中
     * 
     * @param filePath 文件绝对路径
     * @param datas 文件体
     * @param header 文件头信息
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static void writeCsvFile(String filePath, List<List<String>> datas, final Object[] header) {
        LOGGER.info("writeCsvFile enter, file={}", filePath);
        CSVPrinter csvFilePrinter = null;
        FileOutputStream foStream = null;
        OutputStreamWriter write = null;
        // 创建 CSVFormat
        CSVFormat csvFileFormat = CSVFormat.DEFAULT.withRecordSeparator(NEW_LINE_SEPARATOR);
        try {
            // 初始化FileWriter,支持append添加
            foStream = new FileOutputStream(filePath, true);
            write = new OutputStreamWriter(foStream, Charsets.UTF_8.toString());
            // 初始化 CSVPrinter
            csvFilePrinter = new CSVPrinter(write, csvFileFormat);
            // 创建CSV文件头
            if (null != header && header.length > 0) {
                // 头格式
                csvFilePrinter.printRecord(header);
            }
            // 数据不为空时,执行写操作
            if (CollectionUtils.isNotEmpty(datas)) {
                LOGGER.info("writeCsvFile write file={}, size={}", filePath, datas.size());
                // 遍历List写入CSV
                for (List<String> data : datas) {
                    csvFilePrinter.printRecord(data);
                }
            }
            LOGGER.info("writeCsvFile write file={} end!", filePath);
        } catch (Exception e) {
            LOGGER.error("writeCsvFile write file error", e);
        } finally {
            // 关闭流
            if (null != csvFilePrinter) {
                try {
                    csvFilePrinter.close();
                } catch (IOException e) {
                    LOGGER.error("writeCsvFile close csvFilePrinter error", e);
                }
            }
            if (null != write) {
                try {
                    write.close();
                } catch (IOException e) {
                    LOGGER.error("writeCsvFile close write error", e);
                }
            }
            if (null != foStream) {
                try {
                    foStream.close();
                } catch (IOException e) {
                    LOGGER.error("writeCsvFile close foStream error", e);
                }
            }
        }
    }

    /**
     * 
     * 请求下载csv文件
     * 
     * @param response 响应体
     * @param csvFilePath 文件绝对路径
     * @param fileName 下载文件名
     * @throws IOException
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static void exportFile(HttpServletResponse response, String csvFilePath, String fileName)
            throws IOException {
        LOGGER.info("exportFile enter, csvFilePath={},fileName={}", csvFilePath, fileName);
        response.setContentType("application/csv;charset=UTF-8");
        response.setHeader("Content-Disposition", "attachment; filename="
                + URLEncoder.encode(fileName.endsWith(".csv") ? fileName : fileName + ".csv", "UTF-8"));
        InputStream in = null;
        try {
            in = new FileInputStream(csvFilePath);
            int len = 0;
            byte[] buffer = new byte[WRITE_SIZE];
            response.setCharacterEncoding(Charsets.UTF_8.toString());
            OutputStream out = response.getOutputStream();
            // 写文件
            while ((len = in.read(buffer)) > 0) {
                out.write(buffer, 0, len);
            }
            LOGGER.info("exportFile end, csvFilePath={},fileName={}", csvFilePath, fileName);
        } catch (FileNotFoundException e) {
            LOGGER.error("exportFile FileNotFoundException error", e);
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (Exception e) {
                    LOGGER.error("exportFile close inputStream error", e);
                }
            }
        }
    }

    /**
     * 下载文件
     * 
     * @param response
     * @param fileName
     * @param datas
     * @param header
     * @throws IOException
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static void exportFile(HttpServletResponse response, String fileName, List<List<String>> datas,
            final Object[] header) throws IOException {
        // 创建临时文件
        File file = createCsvFile(fileName);
        // 文件存在时
        if (null != file) {
            // 生成CSV文件
            writeCsvFile(file.getAbsolutePath(), datas, header);
            // 写入响应流中
            exportFile(response, file.getAbsolutePath(), fileName);
            // 删除临时文件
            if (!file.delete()) {
                LOGGER.error("exportFile delete temp file error");
            }
        }
    }
    
    /**
     * 
     * 功能描述: 生成CSV文件<br>
     * 〈功能详细描述〉
     *
     * @param fileName
     * @param header
     * @param datas
     * @return
     * @throws IOException
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static File exportFile(String fileName, final Object[] header, List<List<String>> datas) throws IOException {
        // 创建临时文件
        File file = createCsvFile(fileName);
        // 文件存在时
        if (null != file) {
            // 生成CSV文件
            writeCsvFile(file.getAbsolutePath(), datas, header);
        }
        return file;
    }

    /**
     * 默认构造函数
     */
    private CsvUtils() {

    }
}
